package cn.chinaunicom.mini.program.dingtalk.openapi.service;

import com.alibaba.fastjson2.JSON;
import org.springframework.stereotype.Component;

import com.dingtalk.api.request.OapiMessageSendToConversationRequest;
import com.dingtalk.api.response.OapiMessageSendToConversationResponse;
import com.taobao.api.ApiException;

import cn.chinaunicom.mini.program.dingtalk.openapi.client.IDingTalkClient;
import cn.chinaunicom.mini.program.dingtalk.openapi.model.enums.DingTalkMsgType;
import lombok.extern.slf4j.Slf4j;

/**
 * @ProjectName: dingtalk-adapter
 * @Package: cn.chinaunicom.mini.program.dingtalk.openapi.service
 * @ClassName: DingTalkMessageAPI
 * @Description: 钉钉消息发送api
 * @Author: wangjc
 * @CreateDate: 2024/6/14
 * @UpdateUser: wangjc
 * @UpdateDate: 2024/6/14
 * @UpdateRemark: 更新内容
 * @Version: 1.0
 */
@Slf4j
@Component
public class DingTalkMessageAPI {

	private OapiMessageSendToConversationRequest.Msg msg = new OapiMessageSendToConversationRequest.Msg();

	/**
	 * 发送文本消息到会话。
	 *
	 * @param req         发送消息的请求参数对象。
	 * @param contentText 消息的文本内容。
	 * @return 发送消息后的响应对象。
	 */
	public OapiMessageSendToConversationResponse sendTextMsg(OapiMessageSendToConversationRequest req,
			String contentText, String accessToken) throws ApiException {
		// 创建文本消息内容对象，并设置消息内容
		// 文本消息
		OapiMessageSendToConversationRequest.Text text = new OapiMessageSendToConversationRequest.Text();
		text.setContent(contentText);

		// 设置消息类型为文本，并将文本消息内容赋值给msg对象
		msg.setText(text);
		msg.setMsgtype(DingTalkMsgType.MSG_TEXT.getType());

		// 执行发送消息操作，返回响应结果
		return execute(req, msg, accessToken);
	}

	/**
	 * 发送图片消息到会话。
	 *
	 * @param req     发送消息的请求对象，包含目标会话等信息。
	 * @param mediaId 图片的媒体ID，用于标识要发送的图片。
	 * @return 发送消息后的响应对象，包含发送结果等信息。
	 */
	public OapiMessageSendToConversationResponse sendImageMsg(OapiMessageSendToConversationRequest req, String mediaId,
			String accessToken) throws ApiException {
		// 创建图片消息对象，并设置图片的媒体ID
		// 图片
		OapiMessageSendToConversationRequest.Image image = new OapiMessageSendToConversationRequest.Image();
		image.setMediaId(mediaId);
		msg.setImage(image);
		// 设置消息类型为图片消息
		msg.setMsgtype(DingTalkMsgType.MSG_IMAGE.getType());
		// 执行发送消息的操作，返回发送结果
		return execute(req, msg, accessToken);
	}

	/**
	 * 发送文件消息到会话。
	 *
	 * @param req     发送消息的请求对象，包含会话类型及目标会话ID等信息。
	 * @param mediaId 文件的媒体ID，用于标识要发送的文件。
	 * @return 返回发送消息的响应对象，包含请求ID、错误码及错误信息等。
	 */
	public OapiMessageSendToConversationResponse sendFileMsg(OapiMessageSendToConversationRequest req, String mediaId,
			String accessToken) throws ApiException {
		// 创建文件消息对象，并设置文件的媒体ID。
		OapiMessageSendToConversationRequest.File file = new OapiMessageSendToConversationRequest.File();
		file.setMediaId(mediaId);

		// 设置消息类型为文件类型，并将文件对象赋值给消息对象。
		msg.setFile(file);
		msg.setMsgtype(DingTalkMsgType.MSG_FILE.getType());

		// 执行消息发送请求，并返回响应结果。
		return execute(req, msg, accessToken);
	}

	/**
	 * 发送Markdown格式的消息到钉钉群聊或个人对话。
	 *
	 * @param req     钉钉接口请求对象，包含消息发送的配置信息。
	 * @param title   消息的标题，用于概括消息的主要内容。
	 * @param content 消息的Markdown格式内容，支持简单的文本格式化。
	 * @return 返回钉钉接口的响应对象，包含消息发送的结果信息。
	 */
	public OapiMessageSendToConversationResponse sendMarkdownMsg(OapiMessageSendToConversationRequest req, String title,
			String content, String accessToken) throws ApiException {
		// 创建Markdown消息对象，并设置消息的标题和内容。
		OapiMessageSendToConversationRequest.Markdown markdown = new OapiMessageSendToConversationRequest.Markdown();
		markdown.setText(content);
		markdown.setTitle(title);

		// 设置消息类型为Markdown，并将Markdown消息对象赋值给请求消息对象。
		msg.setMarkdown(markdown);
		msg.setMsgtype(DingTalkMsgType.MSG_MARKDOWN.getType());

		// 执行消息发送请求，返回发送结果。
		return execute(req, msg, accessToken);
	}

	/**
	 * 发送ActionCard消息到对话中。
	 *
	 * 该方法用于构建并发送一种特定类型的消息到钉钉对话中，消息类型为ActionCard。
	 * ActionCard消息允许包含一个按钮，用户点击按钮后可以执行特定的操作，比如跳转到指定的URL。
	 *
	 * @param req             发送消息的请求对象，包含必要的配置信息。
	 * @param title           消息的标题，用于显示在ActionCard的顶部。
	 * @param markdownContent 消息的markdown内容，用于展示富文本信息。
	 * @param singleTitle     单个按钮的标题，用户点击后将执行相应操作。
	 * @param singleUrl       单个按钮的URL，用户点击按钮后将跳转到该URL。
	 * @return 返回发送消息后的响应对象，包含钉钉服务器的响应信息。
	 */
	public OapiMessageSendToConversationResponse sendActionCardMsg(OapiMessageSendToConversationRequest req,
			String title, String markdownContent, String singleTitle, String singleUrl, String accessToken) throws ApiException {
		// 创建ActionCard对象，并设置消息的标题、markdown内容、单个按钮的标题和URL。
		OapiMessageSendToConversationRequest.ActionCard actionCard = new OapiMessageSendToConversationRequest.ActionCard();
		actionCard.setTitle(title);
		actionCard.setMarkdown(markdownContent);
		actionCard.setSingleTitle(singleTitle);
		actionCard.setSingleUrl(singleUrl);

		// 将ActionCard对象设置到消息请求中，并指定消息类型为ActionCard。
		msg.setActionCard(actionCard);
		msg.setMsgtype(DingTalkMsgType.MSG_ACTION_CARD.getType());

		// 执行消息发送请求，并返回钉钉服务器的响应。
		return execute(req, msg, accessToken);
	}

	/**
	 * 发送链接消息到钉钉群聊或单聊。
	 *
	 * @param req         钉钉接口请求对象，包含发送消息的必要信息。
	 * @param title       消息链接标题。
	 * @param content     消息链接内容。
	 * @param picMiediaId 图片媒体ID，用于显示消息中的图片。
	 * @param messageUrl  消息链接点击后跳转的URL。
	 * @return 返回钉钉接口的响应对象，包含发送消息的结果信息。
	 */
	public OapiMessageSendToConversationResponse sendLinkMsg(OapiMessageSendToConversationRequest req, String title,
			String content, String picMiediaId, String messageUrl, String accessToken) throws ApiException {
		// 创建链接消息对象
		OapiMessageSendToConversationRequest.Link link = new OapiMessageSendToConversationRequest.Link();
		// 设置链接消息的各个属性
		link.setMessageUrl(messageUrl);
		link.setPicUrl(picMiediaId);
		link.setText(content);
		link.setTitle(title);
		// 设置消息类型为链接类型
		msg.setLink(link);
		msg.setMsgtype("link");
		// 执行消息发送请求，返回发送结果
		return execute(req, msg, accessToken);
	}

	private OapiMessageSendToConversationResponse execute(OapiMessageSendToConversationRequest req,
		OapiMessageSendToConversationRequest.Msg msg, String accessToken) throws ApiException {
		req.setMsg(msg);
		OapiMessageSendToConversationResponse rsp = IDingTalkClient
				.execute("https://oapi.dingtalk.com/message/send_to_conversation", req, accessToken);
		log.debug("钉钉开放平台接口响应体：{}", JSON.toJSONString(rsp.getBody()));
		return rsp;
	}
}
